/**
 * @file schedule.c
 * @synopsis  调度otdr通道使用spi进行测量
 * @author wen wjcapple@163.com
 * @version 2.0
 * @date 2016-06-24
 */
#include <semaphore.h>

#include "otdr_ch.h"
#include "hb_app.h"
#include "global.h"
#include "adpt_otdr.h"
#include "adpt_alarm.h"
//定义otdr通道资源
struct _tagOtdrDev *otdrDev;
//用户点名测量，配置测量
struct _tagUsrOtdrTest usrOtdrTest;
//算法运行时当前的通道信息,开始测量的时候赋值，算法运行完毕清空
//spi 读取数据的缓冲区 spi 数据格式： fe 4B 2B fe 4B 2B
#define SPI_OP_SPACE_MS		1000 //spi设备的操作间隔  
sem_t sem_UsrTest;
pthread_mutex_t mutex_measur;
_tagSpiDevCtrl spi_ctrl;
struct fpga_dev *fpga_device;
struct _tagCuState cu_state;
//记录线程信息
struct _tagThreadInfo tsk_debug_info;
struct _tagThreadInfo tsk_measur_info;
struct _tagThreadInfo tsk_service_info;
struct _tagCHAlarmDis chAlarmDis;
int32_t tsk_debug(void *arg)
{
	struct _tagThreadInfo *pthread_info;
	pthread_info = (struct _tagThreadInfo *)arg;
	pthread_info->top_id = (long int)syscall(224);

	printf("%s %s  pid %d  self_id 0x%x \n",__FILENAME__, __FUNCTION__, (long int)syscall(224),(int)pthread_self());

	while(1){
		ret_total_curalarm2host();
		printf("%s %d sleep \n", __FUNCTION__, __LINE__);
		//usr_delay(0, SPI_OP_SPACE_MS);
		printf("%s %d get up \n", __FUNCTION__, __LINE__);
	}
	pthread_exit(0);
}

extern struct _tagIpSwitchCtr IPCtrl;
int32_t check_net_falg(struct ep_t *pep, char dst_ip[])
{
	int32_t net_sec, fd;
	if(cu_state.state == 1)
		read_net_flag(1);
	else
		read_net_flag(0);
	if(IPCtrl.re_connect){
		IPCtrl.re_connect = 0;
		net_sec = IPCtrl.flag ^ 1;
		snprintf(dst_ip,16 , "192.168.%d.254",net_sec);
		fd =  tms_SelectFdByAddr(ADDR_CU);

		if(fd > 0)
			ep_Close(pep,NULL,fd);
		
	}
	return 0;
}

struct _tagTickCount TickCount;
int32_t check_connect2cu(char dst_ip[],int32_t *pstate)
{
	struct ep_con_t  epnode;
	struct glink_addr addr;
	int32_t dst_port = 6000, net_sec, fd;
	int32_t state, ret;
	struct tms_context *pcontext;
	static int32_t reconnect_num = 0, reconnect_count = 0;
	static int32_t count = 0, report_count = 0;
	addr.dst = ADDR_CU;
	addr.src = ADDR_LOCAL;
	addr.pkid = get_pkid();
	//检查CU是否失去连接
	fd =  tms_SelectFdByAddr(ADDR_CU);
	count++;
	/*
	 *第一次重连的间隔是1秒，第n次重连的间隔是n*1
	 */
	state = 1;
	if(fd < 0 && reconnect_count >= reconnect_num){
		epnode.sockfd = -1;
		reconnect_count = 0;
		PR_X("connect dst ip %s port %d \n",dst_ip, dst_port);
		ep_Connect(&ep_client, &epnode, dst_ip,dst_port);
		if(epnode.sockfd != -1)
		{
			report_count = 0;
			//RetLocalCardType(&(((struct tmsxx_app*)(epnode.ptr))->context));
			tms_RefreshAddrFd(epnode.sockfd, ADDR_CU);
			reconnect_num = 0;
			reconnect_count = 0;
			write_gpio_val(gpio_fd.alarm_total_1,0);
			state = 0;
			TickCount.src_e = 0;
		}
		else if(reconnect_num >= 20)
			reconnect_num = 20;
		else 
			reconnect_num++;
	}
	else if(fd < 0)
		reconnect_count++;
		
	else 
	{
		reconnect_num = 0;
		reconnect_count = 0;
		state = 0;
		if(report_count < 5)
		{
			ret = get_context_by_dst(ADDR_CU,&pcontext);
			if(ret == 0)
				RetLocalCardType(pcontext);
			else
				printf("%s %d can't report card type ret %d \n", __FUNCTION__,__LINE__,ret);
		}
		report_count++;
		if(count % 2 == 0)
		{
			TickCount.src_e++;
			tms_Tick(fd, &addr);
			if(TickCount.src_e >= 8)
			{
				ep_Close(&ep_client,NULL,fd);
				state = 1;
			}
		}


	}
	//17-09-30维纳迪，如果连接不上，红灯闪，连接10次以上开始闪红灯
	/*
	if(reconnect_num >= 10)
		*pstate = 1;
	else 
		*pstate = 0;
	*/
	if(reconnect_num >= 10)
		 write_gpio_val(gpio_fd.alarm_total_1,1);

	*pstate = state;
	assert(reconnect_num <= 4000);
	return 0;


}
/* --------------------------------------------------------------------------*/
/**
 * @synopsis  tsk_connect,检查网络连接以及重连
 *
 * @param arg
 *
 * @returns   
 */
/* ----------------------------------------------------------------------------*/
extern struct ep_t ep_client;
struct _tagThreadInfo tsk_connect_info;
int32_t tsk_connect(void *arg)
{
	struct _tagThreadInfo *pthread_info;
	//struct _tagCuState cu_state;
	int32_t delay_us = 1000000;
	int32_t ret, count; 
	struct tms_context *pcontext;
	char dst_ip[16];
	int32_t net_sec;

	pthread_info = (struct _tagThreadInfo *)arg;
	pthread_info->top_id = (long int)syscall(224);

	PR_X("pid %d  self_id 0x%x \n",(long int)syscall(224),(int)pthread_self());
	memset(&cu_state, 0, sizeof(struct _tagCuState));
	count = 0;

	net_sec = IPCtrl.flag ^ 1;
	snprintf(dst_ip,16 , "192.168.%d.254",net_sec);

	while(1){

		//检查是否切换网段，如果切换网段，主动关掉连接
		if(count % 2 == 0)
			check_net_falg(&ep_client,dst_ip);


		//检查连接是否存在
		if(count % 4 == 0)
			check_connect2cu(dst_ip, &cu_state.state);

		count++;	
		usleep(delay_us);
	}
	pthread_exit(0);
}

extern unsigned int fpga_alive(struct fpga_dev *dev);
int32_t tsk_service(void *arg)
{
	struct _tagThreadInfo *pthread_info;
	int32_t delay_us = 500000;
	int32_t ret, count, val; 
	struct tms_context *pcontext;

	pthread_info = (struct _tagThreadInfo *)arg;
	pthread_info->top_id = (long int)syscall(224);

	PR_X("pid %d  self_id 0x%x \n",(long int)syscall(224),(int)pthread_self());


	count = 0;
	val = 0;
	while(1)
	{
		if(cu_state.state)
			delay_us = 2000000;
		else
			delay_us = 500000;

		run_green_led_blink();

		if(count % 8 == 0 && fpga_device != NULL)
			fpga_alive(fpga_device);


		//运行灯闪烁
		blink_ch_test_led();
		count++;	
		usleep(delay_us);
	}
	pthread_exit(0);
}

//存放算法曲线的缓冲区
float algorAi[DATA_LEN];
extern struct _tagOtdrTestCtrl otdrTestCtrl;
int32_t tsk_measur(void *arg)
{
	struct _tagThreadInfo *pthread_info;
	pthread_mutex_t *pmutex;
	OtdrTestResult_t ch_tr;
	int32_t ret, ch;


	pmutex = &mutex_measur;
	pthread_info = (struct _tagThreadInfo *)arg;
	pthread_info->top_id = (long int)syscall(224);
	ch_tr.Ai = algorAi;
	printf("%s %s  pid %d  self_id 0x%x \n",__FILENAME__, __FUNCTION__, (long int)syscall(224),(int)pthread_self());

	while(1)
	{

		//处理点名测量
		ret = sem_wait(&sem_UsrTest);
		if(ret == 0)
		{
			if(usrOtdrTest.state == USR_OTDR_TEST_WAIT)
			{
				otdrTestCtrl.stop = 0;
				ch = usrOtdrTest.para.pipe;
				chAlarmDis.ch[ch] = 1;
				deal_appoint_test(&usrOtdrTest,&ch_tr,&spi_ctrl,cb_stop);
				chAlarmDis.ch[ch] = 0;
			}
		}
	}



}
